//
//  PhotoAsset.m
//  XPhoto
//
//  Created by baboy on 2019/6/11.
//  Copyright © 2019 baboy. All rights reserved.
//

#import "PhotoAsset.h"
#import "PHAsset+x.h"

UIInterfaceOrientation AVAssetOrientation(AVAsset *asset){
    NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
    if([tracks count] > 0) {
        AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
        
        CGAffineTransform t = videoTrack.preferredTransform;
        // Portrait
        if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0)
        {
            return UIInterfaceOrientationPortrait;
        }
        // PortraitUpsideDown
        if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0)  {
            
            return UIInterfaceOrientationPortraitUpsideDown;
        }
        // LandscapeRight
        if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0)
        {
            return UIInterfaceOrientationLandscapeRight;
        }
        // LandscapeLeft
        if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0)
        {
            return UIInterfaceOrientationLandscapeLeft;
        }
    }
    return UIInterfaceOrientationUnknown;
}

@implementation PhotoAsset
- (id)initWithAsset:(nullable PHAsset*)asset thumbnail:(nullable UIImage*)thumbnail{
    if (self = [self init]) {
        self.asset = asset;
        self.thumbImage = thumbnail;
    }
    return self;
}
- (id)initWithAsset:(nullable PHAsset*)asset{
    if (self = [self init]) {
        self.asset = asset;
    }
    return self;
}

+ (void)mergeVideos:(NSArray *)videos
         toFilePath:(NSURL *)fileURL
           progress:(void (^)(CGFloat))progress
         completion:(void (^)(NSError *,PhotoAsset*))completion{
    if(videos.count == 1){
        PhotoAsset *photoAsset = videos.firstObject;
        if(completion){
            completion(nil, photoAsset);
        }
        return;
    }
    //这是工程文件
    AVMutableComposition *composition = [AVMutableComposition composition];
    //视频轨道
    AVMutableCompositionTrack *videoCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    //音频轨道
    AVMutableCompositionTrack *audioCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    CMTime timePositon = kCMTimeZero;
    NSMutableArray *instructions = [NSMutableArray new];
    int32_t maxFrameRate = 0;
    BOOL isVideoPortrait = NO;
    CGSize videoSize = CGSizeZero;
    for (NSInteger i = 0, n = videos.count; i < n; i++) {
        PhotoAsset *photoAsset = [videos objectAtIndex:i];
        AVAsset  *asset = [AVAsset assetWithURL:photoAsset.assetURL];
        //素材的视频轨
        AVAssetTrack *videoAssetTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
        //素材的音频轨
        AVAssetTrack *audioAssertTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
        
        
        //在视频轨道插入一个时间段的视频
        [videoCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAssetTrack.timeRange.duration) ofTrack:videoAssetTrack atTime:timePositon error:nil];
        //插入音频数据，否则没有声音
        [audioCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAssetTrack.timeRange.duration) ofTrack:audioAssertTrack atTime:timePositon error:nil];
        
        
        //调整方向
        AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoAssetTrack];
        
        [layerInstruction setTransform:videoAssetTrack.preferredTransform atTime:timePositon];
        
        
        AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
        instruction.timeRange = CMTimeRangeMake(timePositon, asset.duration);
        instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction];
        [instructions addObject:instruction];
        UIInterfaceOrientation videoOrientation = AVAssetOrientation(asset);
        if ( videoOrientation == UIInterfaceOrientationPortrait || videoOrientation == UIInterfaceOrientationPortraitUpsideDown ) {
            isVideoPortrait = YES;
        }
        if ( CGSizeEqualToSize(videoSize, CGSizeZero) ){
            videoSize = videoAssetTrack.naturalSize;
        }
        
        int32_t currentFrameRate = (int)roundf(videoAssetTrack.nominalFrameRate);
        maxFrameRate = MAX(maxFrameRate, currentFrameRate);
        
        timePositon = CMTimeAdd(timePositon, asset.duration);
    }
    AVMutableVideoComposition *videoComposition =[AVMutableVideoComposition videoComposition];
    videoComposition.instructions = instructions;
    videoComposition.renderSize = CGSizeMake(MIN(videoSize.width, videoSize.height), MAX(videoSize.width, videoSize.height));
    videoComposition.frameDuration = CMTimeMake(1, maxFrameRate);
    
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality];
    exporter.videoComposition = videoComposition;
    exporter.outputURL = fileURL;
    exporter.outputFileType = AVFileTypeMPEG4;
    exporter.shouldOptimizeForNetworkUse = YES;
    NSTimer *progressTimer = [NSTimer scheduledTimerWithTimeInterval:0.5f repeats:YES block:^(NSTimer * _Nonnull timer) {
        if (progress) {
            dispatch_async(dispatch_get_main_queue(), ^{                
                progress(exporter.progress);
            });
        };
        if (exporter.progress == 1.0) {
            [timer invalidate];
        }
    }];
    [exporter exportAsynchronouslyWithCompletionHandler:^{
        switch(exporter.status) {
            case AVAssetExportSessionStatusFailed:{
                NSLog(@"exporting failed %@",[exporter error]);
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (completion) {
                        completion(exporter.error,nil);
                    }
                });
                break;
            }
            case AVAssetExportSessionStatusCompleted:{
                NSLog(@"导出完成");
                dispatch_async(dispatch_get_main_queue(), ^{
                    progress(exporter.progress);
                });
                [PHAsset saveVideoToPhotoLib:fileURL
                               resultHandler:^(PHAsset * _Nonnull asset, NSError * _Nonnull error) {
                    dispatch_async(dispatch_get_main_queue(), ^{

                        PhotoAsset *photoAsset = nil;
                        if (!error) {
                            PhotoAsset *firstClip = videos.firstObject;
                            photoAsset = [PhotoAsset new];
                            photoAsset.asset = asset;
                            photoAsset.type = PhotoAssetTypeVideo;
                            photoAsset.duration = timePositon.value*1.0f/timePositon.timescale;
                            photoAsset.thumbImage = [firstClip thumbImage];
                            photoAsset.originImage = [firstClip originImage];
                            photoAsset.originPath = photoAsset.originPath;
                            photoAsset.assetURL = fileURL;
                        }
                        if (completion) {
                            completion(error, photoAsset);
                        }
                    });
                }];
                break;
            }
            case AVAssetExportSessionStatusCancelled:
                NSLog(@"export cancelled");
                break;
            case AVAssetExportSessionStatusUnknown:
                break;
            case AVAssetExportSessionStatusWaiting:
                break;
            case AVAssetExportSessionStatusExporting:
                if (progress) {
                    progress(exporter.progress);
                }
                break;
        }// end switch
        [progressTimer invalidate];
     }];
    
}
@end

